home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
BMUG Revelations
/
BMUG Revelations.toast
/
Utilities
/
Random
/
Commodore 64c
/
SOURCE
/
VIC.c
< prev
Wrap
Text File
|
1994-03-15
|
8KB
|
273 lines
/*
Commodore 64 Emulator v0.1 Earle F. Philhower III
Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "Memory.h"
#include "MemoryCalls.h"
#include "Error.h"
void TotalRedrawVIC(void);
#define FastDraw(a, b, c) \
{ \
thisLine=(char**)&(lineStart[(word)((a)<<3)]); \
theseDefs=(char*)(VICCharDefs+(word)((c)<<3)); \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
*(*thisLine++ + b)=*theseDefs++; \
}
WindowPtr VICWind;
byte VICText[1024], VICRegister[0x2f];
word VICAddrBase, VICScreenPage, VICCharBase;
byte VICBank, *VICCharDefs;
byte *lineStart[200];
Rect fullRect, leftRect, rightRect, topRect, botRect, spr;
BitMap saveMap, spriteMap, VICMap, fullMap;
GrafPtr spriteGraf;
byte CreateOffscreenBitMap(GrafPtr *newOffscreen, Rect *inBounds)
{
GrafPtr savePort, newPort;
GetPort(&savePort);
newPort = (GrafPtr)GetMemory(sizeof(GrafPort));
OpenPort(newPort);
newPort->portRect = *inBounds;
newPort->portBits.bounds = *inBounds;
RectRgn(newPort->clipRgn, inBounds);
RectRgn(newPort->visRgn, inBounds);
newPort->portBits.rowBytes =
((inBounds->right - inBounds->left + 15) >> 4) << 1;
newPort->portBits.baseAddr = (Ptr)
GetMemory(newPort->portBits.rowBytes*(long)(inBounds->bottom-inBounds->top));
if(MemError() != noErr) {
SetPort(savePort);
ClosePort(newPort);
DisposPtr((Ptr)newPort);
return 0;}
EraseRect(inBounds);
*newOffscreen = newPort;
SetPort(savePort);
return 1;
}
Ptr NewBitMap(BitMap *theBits, Rect *rp)
{
theBits->rowBytes=((rp->right-rp->left+15)/16)*2;
theBits->baseAddr=(Ptr)GetMemory(theBits->rowBytes*(rp->bottom-rp->top));
theBits->bounds=*rp;
return(theBits->baseAddr);
}
int VICInitialize()
{
int row, col, chr;
row=col=0;
SetRect(&fullRect,0,0,320,200);
SetRect(&leftRect,0,0,7,200);
SetRect(&rightRect,320-8,0,320,200);
SetRect(&topRect,0,0,320,4);
SetRect(&botRect,0,200-4,320,200);
SetRect(&spr,0,0,24,21);
VICWind=GetNewWindow(128,nil,(void *)-1L);
if (VICWind==nil) return(kWindowMissing);
ShowWindow(VICWind);
SetPort(VICWind);
SelectWindow(VICWind);
if (NewBitMap(&spriteMap, &spr)==0) return kOutOfMemory;
if (NewBitMap(&VICMap, &fullRect)==0) return kOutOfMemory;
if (NewBitMap(&fullMap, &fullRect)==0) return kOutOfMemory;
for (row=0; row<200; row++)
lineStart[row]=(byte *)VICMap.baseAddr+40*row;
return(kNoError);
}
void VICAddrAdjust()
{
VICBank=(RAM[0xdd00]&3)^3;
VICAddrBase=VICBank*16384;
VICScreenPage=((RAM[0xd018]&0xf0)>>4)*0x0400+VICAddrBase;
VICCharBase=((RAM[0xd018]&0x0e)*1024);
if ((VICBank==1)||(VICBank==3))
VICCharDefs=RAM+(VICAddrBase+VICCharBase);
else
if (VICCharBase==4096) VICCharDefs=charROM;
else if (VICCharBase==6144) VICCharDefs=charROM+0x0800;
else VICCharDefs=RAM+(VICAddrBase+VICCharBase);
}
byte NotSameVIC()
{
register byte addr;
for (addr=0; addr<0x2f; addr++) {
if (addr==0x11)
{ if ((RAM[0xd011]&127)!=(VICRegister[0x11]&127))
return 1;}
else if (addr==0x12);
else if (RAM[0xd000+addr]!=VICRegister[addr]) return 1; }
return 0;
}
void DrawSprites()
{
byte spriteNum, row, *spb0, *spb1, *spb2;
word xpos, ypos, addr0, addr1, addr2;
Rect t;
BlockMove(VICMap.baseAddr, fullMap.baseAddr, GetPtrSize(VICMap.baseAddr));
saveMap = qd.thePort->portBits;
SetPortBits(&spriteMap);
for (spriteNum=0; spriteNum<8; spriteNum++)
if (VICRegister[0x15]&(1<<spriteNum)) {
xpos=VICRegister[0x00+spriteNum*2]-24;
ypos=VICRegister[0x01+spriteNum*2]-50;
xpos += (VICRegister[0x10]&(1<<spriteNum))?256:0;
t.top=ypos;t.left=xpos;
t.right=t.left+24+((VICRegister[0x1d]&(1<<spriteNum))?24:0);
t.bottom=t.top+21+((VICRegister[0x17]&(1<<spriteNum))?21:0);
addr0 = VICAddrBase+RAM[VICScreenPage+1016+spriteNum]*64;
addr1= addr0+1; addr2=addr0+2;
spb0=(byte *)spriteMap.baseAddr; spb1=spb0+1; spb2=spb0+2;
for (row=0; row<21; row++) {
spb0[row<<2]=RAM[addr0+row*3];
spb1[row<<2]=RAM[addr1+row*3];
spb2[row<<2]=RAM[addr2+row*3]; }
CopyBits(&spriteMap,&fullMap,&spr,&t,srcOr,nil); }
SetPortBits(&saveMap);
SetPort(VICWind);
}
/*
void ScrollScreen()
{
word xscroll, yscroll;
xscroll=VICRegister[0x16]&7; yscroll=(VICRegister[0x11]&7)-3;
if (yscroll>0)
BlockMove(lineStart[0],lineStart[yscroll],(320/8)*(200-yscroll));
else if (yscroll<0)
BlockMove(line
*/
void DrawTextScreen(byte total)
{
word chr;
byte row, col;
register char **thisLine;
register char *theseDefs;
row=col=0;
saveMap=qd.thePort->portBits;
SetPortBits(&VICMap);
/* SetOrigin(-(VICRegister[0x16]&7),-((VICRegister[0x11]&7)-3));*/
if (VICRegister[0x11]&32) {
VICCharDefs=RAM+VICAddrBase+((VICRegister[0x18]&8)?8192:0);
for (chr=0;chr<1000;chr++) {
FastDraw(row,col,chr);
col++;if (col>39) {col=0;row++;} }
}
else {
if (total)
for (chr=0;chr<1000;chr++) {
FastDraw(row,col,RAM[chr+VICScreenPage]);
VICText[chr]=RAM[chr+VICScreenPage];
col++;if (col>39) {col=0;row++;} }
else
for (chr=0;chr<1000;chr++) {
if (VICText[chr]!=RAM[chr+VICScreenPage]) {
FastDraw(row,col,RAM[chr+VICScreenPage]);
VICText[chr]=RAM[chr+VICScreenPage]; }
col++;if (col>39) {col=0;row++;} } }
/* SetOrigin(0,0);*/
SetPortBits(&saveMap);
/* ScrollRect(&fullRect, VICRegister[0x16]&7,(VICRegister[0x11]&7)-3,nil);*/
}
void DrawBorders()
{
saveMap=qd.thePort->portBits;
SetPortBits(&VICMap);
if (VICRegister[0x16]&8);else {FillRect(&leftRect,(PatPtr)&qd.black);FillRect(&rightRect,(PatPtr)&black);}
if (VICRegister[0x11]&8);else {FillRect(&botRect,(PatPtr)&black);FillRect(&topRect,(PatPtr)&black);}
SetPortBits(&saveMap);
}
void CopyTextToScreen()
{
SetPort(VICWind);
CopyBits(&VICMap,&(VICWind->portBits),&fullRect,&fullRect,srcCopy,nil);
}
void CopySpritesToScreen()
{
SetPort(VICWind);
CopyBits(&fullMap,&(VICWind->portBits),&fullRect,&fullRect,srcCopy,nil);
}
void BlankScreen()
{
saveMap = qd.thePort->portBits;
SetPortBits(&VICMap);
FillRect(&fullRect, (PatPtr)&qd.gray);
SetPortBits(&saveMap);
CopyTextToScreen();
return;
}
void RedrawVIC()
{
if (NotSameVIC()) { TotalRedrawVIC(); return; }
VICAddrAdjust();
SetPort(VICWind);
if (VICRegister[0x11]&16); else { BlankScreen(); return;}
DrawTextScreen(0);
DrawBorders();
if (VICRegister[0x15]) { DrawSprites(); CopySpritesToScreen();}
else CopyTextToScreen();
}
void TotalRedrawVIC()
{
register byte addr;
for (addr=0; addr<0x2f; addr++) VICRegister[addr]=RAM[0xd000+addr];
VICAddrAdjust();
SetPort(VICWind);
if (VICRegister[0x11]&16); else { BlankScreen(); return;}
DrawTextScreen(1);
DrawBorders();
if (VICRegister[0x15]) { DrawSprites(); CopySpritesToScreen();}
else CopyTextToScreen();
}